package com.ssy.lingxi.system.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.system.dao.*;
import com.ssy.lingxi.system.dto.request.*;
import com.ssy.lingxi.system.dto.response.*;
import com.ssy.lingxi.system.entity.*;
import com.ssy.lingxi.system.model.constant.RoleConstant;
import com.ssy.lingxi.system.service.MiddlegroundUserService;
import com.ssy.lingxi.system.utils.FileMd5Utils;
import com.ssy.lingxi.system.utils.UserDetailsUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class MiddlegroundUserServiceImpl implements MiddlegroundUserService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    MiddlegroundUserRepository middlegroundUserRepository;
    @Autowired
    MiddlegroundMenuRepository middlegroundMenuRepository;
    @Autowired
    MiddlegroundRoleUserRepository middlegroundRoleUserRepository;
    @Autowired
    MiddlegroundRoleRepository middlegroundRoleRepository;
    @Autowired
    MiddlegroundMenuRoleRepository middlegroundMenuRoleRepository;
    @Autowired
    UserDetailsUtil userDetailsUtil;
    @Resource
    private EntityManager entityManager;
    @Autowired
    JdbcTemplate jdbcTemplate;

    public MiddlegroundUserServiceImpl() {
    }

    @Override
    public Wrapper<PageData<MiddlegroundUserResponse>> middlegroundUserList(MiddlegroundUserRequest request) {
        StringBuilder sbList=new StringBuilder();
        StringBuilder sbCount=new StringBuilder();
        StringBuilder sbCondition=new StringBuilder();
        sbList.append("select  distinct mu.id,mu.account as account,mu.name as name,mu.state as state,mu.tel as tel, mu.update_time as updateTime from cf_middleground_user mu  left join cf_middleground_role_user mru on mu.id=mru.user_id left join cf_middleground_role mr on mr.id=mru.role_id where 1=1 ");
        sbCount.append("select count(distinct mu.id) from cf_middleground_user mu  left join cf_middleground_role_user mru on mu.id=mru.user_id left join cf_middleground_role mr on mr.id=mru.role_id where 1=1 ");
        if(null!=request.getState()){
            sbCondition.append(" and  mu.state= ");
            sbCondition.append(request.getState());
        }
        if(null!=request.getName()&&!request.getName().isEmpty()){
            sbCondition.append(" and mu.name like  '%");
            sbCondition.append(request.getName());
            sbCondition.append("%'");
        }
        if(null!=request.getAccount()&&!request.getAccount().isEmpty()){
            sbCondition.append(" and  mu.account=");
            sbCondition.append(request.getAccount());
            sbCondition.append(" ");
        }
        sbCount.append(sbCondition.toString());
        sbList.append(sbCondition.toString());
        sbList.append(" limit ");
        sbList.append(request.getPageSize());
        sbList.append(" OFFSET ");
        sbList.append(request.getCurrent());
        Long count = jdbcTemplate.queryForObject(sbCount.toString(), Long.class);
        List<MiddlegroundUserResponse> query = jdbcTemplate.query(sbList.toString(), new BeanPropertyRowMapper(MiddlegroundUserResponse.class));
        Set<Long> roleIds = query.stream().map(object -> object.getId()).collect(Collectors.toSet());
        StringBuilder roleSql=new StringBuilder("select ru.user_id AS userId,mr.name as roleName  FROM  cf_middleground_role mr LEFT JOIN cf_middleground_role_user ru ON ru.role_id = mr.id  where ru.user_id in(");
        roleIds.forEach(id->{
            roleSql.append(id).append(",");
        });
        roleSql.deleteCharAt(roleSql.length() - 1);
        roleSql.append(")");
        List<MiddlegroundRoleUserDto> roleNames = jdbcTemplate.query(roleSql.toString(), new BeanPropertyRowMapper(MiddlegroundRoleUserDto.class));
        query.forEach(middlegroundUserResponse->{
            List<String> roleNmaes=new ArrayList<>();
            roleNames.forEach(middlegroundRoleUserDto->{
                if(null!=middlegroundRoleUserDto.getUserId()&&middlegroundRoleUserDto.getUserId().equals(middlegroundUserResponse.getId())){
                    roleNmaes.add(middlegroundRoleUserDto.getRoleName());
                }
            });
            middlegroundUserResponse.setRoleNames(roleNmaes);
        });
        return Wrapper.success(new PageData(count, query));
    }



    @Override
    public Wrapper<LoginResponse> middlegroundUserLogin(HttpServletRequest request, MiddlegroundUserLoginRequest dtoRequest) {
        //TODO 是否频繁登录
        //查询用户信息
        MiddlegroundUserLoginResponse loginMiddlegroundUserLoginResponse = getLoginMiddlegroundUserLoginResponse(dtoRequest.getAccount());
        if(null==loginMiddlegroundUserLoginResponse){
            return Wrapper.fail("账号不存在");
        }
        //验证用户密码
        String md5 = FileMd5Utils.getMD5("lixi".concat(dtoRequest.getPassword()), true, 32);
        if(!md5.equals(loginMiddlegroundUserLoginResponse.getPassword())){
            return Wrapper.fail("密码错误");
        }
        //上次登录时间是否超过系统风险判断 TODO 先注释
//        int dayNum = DateUtils.differentDaysByMillisecond(loginMiddlegroundUserLoginResponse.getFinallyLoginTime(), System.currentTimeMillis());
//        if(dayNum>10){
//            return Wrapper.fail("长时间没有登录请输入手机验证码");
//        }
        //保存用户信息到缓存中
        String token =FileMd5Utils.getMD5("lixi".concat(dtoRequest.getAccount()).concat(System.currentTimeMillis()+""),true, 32);

        //改成使用fasterxml.jackson
        //Modified by: 万宁 2020-05-27
        String loginMiddlegroundUserLoginResponseJsonStr = null;
        ObjectMapper mapper = new ObjectMapper();
        try {
            loginMiddlegroundUserLoginResponseJsonStr = mapper.writeValueAsString(loginMiddlegroundUserLoginResponse);
        } catch (Exception e) {
            return Wrapper.fail("用户信息异常");
        }

        stringRedisTemplate.opsForValue().set(token, loginMiddlegroundUserLoginResponseJsonStr,7200, TimeUnit.SECONDS);

        //stringRedisTemplate.opsForValue().set(token, JSON.toJSONString(loginMiddlegroundUserLoginResponse),7200, TimeUnit.SECONDS);

        //更新登录时间
        Optional<MiddlegroundUser> byId = middlegroundUserRepository.findById(loginMiddlegroundUserLoginResponse.getId());
        MiddlegroundUser middlegroundUser = byId.get();
        middlegroundUser.setFinallyLoginTime(System.currentTimeMillis());
        middlegroundUserRepository.save(middlegroundUser);
        LoginResponse loginResponse=new LoginResponse();
        loginResponse.setToken(token);
        return Wrapper.success(loginResponse);
    }

    @Override
    public Wrapper<MiddlegroundUserLoginResponse> middlegroundUserDetails(HttpServletRequest dtoRequest) {
        String token = dtoRequest.getHeader("token");
        String middlegroundUserLoginResponseStr = stringRedisTemplate.opsForValue().get(token);
        if(null==middlegroundUserLoginResponseStr||middlegroundUserLoginResponseStr.isEmpty()){
            Wrapper.fail("登录已过期");
        }

        //改成使用fasterxml.jackson
        ObjectMapper mapper = new ObjectMapper();
        MiddlegroundUserLoginResponse middlegroundUserLoginResponse = null;
        try {
            middlegroundUserLoginResponse = mapper.readValue(middlegroundUserLoginResponseStr,MiddlegroundUserLoginResponse.class);
        } catch (Exception e) {
            return Wrapper.fail("用户信息异常");
        }

        //MiddlegroundUserLoginResponse middlegroundUserLoginResponse = JSON.parseObject(middlegroundUserLoginResponseStr, MiddlegroundUserLoginResponse.class);

        stringRedisTemplate.opsForValue().set(token,middlegroundUserLoginResponseStr,7200, TimeUnit.SECONDS);
        middlegroundUserLoginResponse.setPassword("");
        return Wrapper.success(middlegroundUserLoginResponse);
    }

    /**
     * 添加用户
     * @param httpServletRequest
     * @param request
     * @author wrc
     * @date 2020/5/22
     */
    @Transactional
    @Override
    public Wrapper middlegroundUserAdd(HttpServletRequest httpServletRequest, MiddlegroundUserAddRequest request) {
        MiddlegroundUserLoginResponse loginUserDetails = userDetailsUtil.getLoginUserDetails(httpServletRequest);
        //判断账号是否存在 判断
        MiddlegroundUser middlegroundUser=new MiddlegroundUser();
        middlegroundUser.setAccount(request.getAccount());
        Example<MiddlegroundUser> example=Example.of(middlegroundUser);
        List<MiddlegroundUser> all = middlegroundUserRepository.findAll(example);
        if(null!=all&&all.size()>0){
            return Wrapper.fail("账号已存在");
        }
        BeanUtils.copyProperties(request,middlegroundUser);
        middlegroundUser.setCreateRole(loginUserDetails.getId());
        middlegroundUser.setState(CommonConstant.State.STATE_START);
        middlegroundUser.setPassword(FileMd5Utils.getMD5("lixi".concat(request.getPassword()), true, 32));
        middlegroundUser.setCreateTime(System.currentTimeMillis());
         MiddlegroundUser save = middlegroundUserRepository.save(middlegroundUser);
         List<MiddlegroundRoleUser> middlegroundRoleUsers=new ArrayList<>();
        Long id = save.getId();
        request.getRoleIds().forEach(roleId->{
            MiddlegroundRoleUser middlegroundRoleUser=new MiddlegroundRoleUser();
            middlegroundRoleUser.setUserId(id);
            middlegroundRoleUser.setRoleId(roleId);
            middlegroundRoleUsers.add(middlegroundRoleUser);
        });
        middlegroundRoleUserRepository.saveAll(middlegroundRoleUsers);
        return Wrapper.success();
    }

    /**
     * 修改用户信息
     * @param request
     * @author wrc
     * @date 2020/7/23
     */
    @Transactional
    @Override
    public Wrapper middlegroundUserUpdate(MiddlegroundUserUpdateRequest request) {
        Optional<MiddlegroundUser> byId = middlegroundUserRepository.findById(request.getId());
        if(!byId.isPresent()){
            return Wrapper.fail("用户信息不存在");
        }
        MiddlegroundUser middlegroundUser = byId.get();
        middlegroundUser.setUpdateTime(System.currentTimeMillis());
        BeanUtils.copyProperties(request,middlegroundUser);
        middlegroundUserRepository.save(middlegroundUser);
        Long id = middlegroundUser.getId();
        middlegroundRoleUserRepository.deleteAllByUserIdEquals(id);
        if(null!=request.getRoleIds()&&request.getRoleIds().size()>0){
            List<MiddlegroundRoleUser> middlegroundRoleUsers=new ArrayList<>();
            request.getRoleIds().forEach(roleId->{
                MiddlegroundRoleUser middlegroundRoleUser=new MiddlegroundRoleUser();
                middlegroundRoleUser.setUserId(id);
                middlegroundRoleUser.setRoleId(roleId);
                middlegroundRoleUsers.add(middlegroundRoleUser);
            });
            middlegroundRoleUserRepository.saveAll(middlegroundRoleUsers);
        }
        return Wrapper.success();
    }

    /**
     * 修改用户状态
     * @param request
     * @author wrc
     * @date 2020/7/23
     */
    @Transactional
    @Override
    public Wrapper middlegroundUserUpdateState(MiddlegroundUserUpdateStateRequest request) {
        Optional<MiddlegroundUser> byId = middlegroundUserRepository.findById(request.getUserId());
        if(!byId.isPresent()){
            return Wrapper.fail("用户信息不存在");
        }
        MiddlegroundUser middlegroundUser = byId.get();
        middlegroundUser.setUpdateTime(System.currentTimeMillis());
        middlegroundUser.setState(request.getState());
        middlegroundUserRepository.save(middlegroundUser);
        return Wrapper.success();
    }

    /**
     * 获取用户信息详情
     * @param request
     * @author wrc
     * @date 2020/7/23
     */

    @Override
    public Wrapper<MiddlegroundUserDetailsResponse> middlegroundUserDetailsById(MiddlegroundUserDetailsRequest request) {
        MiddlegroundUserDetailsResponse middlegroundUserDetailsResponse=new MiddlegroundUserDetailsResponse();
        Optional<MiddlegroundUser> byId = middlegroundUserRepository.findById(request.getUserId());
        if(!byId.isPresent()){
            return Wrapper.fail("用户信息不存在");
        }
        MiddlegroundUser middlegroundUser = byId.get();
        BeanUtils.copyProperties(middlegroundUser,middlegroundUserDetailsResponse);
        MiddlegroundRoleUser  middlegroundRoleUser =new MiddlegroundRoleUser();
        middlegroundRoleUser.setUserId(middlegroundUser.getId());
        Example<MiddlegroundRoleUser> middlegroundRoleUserExample = Example.of(middlegroundRoleUser);
        List<MiddlegroundRoleUser> roleUseAll = middlegroundRoleUserRepository.findAll(middlegroundRoleUserExample);
        //获得角色列表
        Set<Long> collect = roleUseAll.stream().map(roleUser -> roleUser.getRoleId()).collect(Collectors.toSet());
        List<MiddlegroundRole> allById = middlegroundRoleRepository.findAllById(collect);
        List<RoleLoginResponse>  roleLoginResponses=new ArrayList<>();
        allById.forEach(role->{
            //获得角色的菜单集合
            MiddlegroundMenuRole  middlegroundMenuRole =new MiddlegroundMenuRole();
            middlegroundMenuRole.setRoleId(role.getId());
            Example<MiddlegroundMenuRole> middlegroundMenuRoleExample = Example.of(middlegroundMenuRole);
            List<MiddlegroundMenuRole> menuRoleAll = middlegroundMenuRoleRepository.findAll(middlegroundMenuRoleExample);
            Set<Long> menuIds = menuRoleAll.stream().map(menuRole -> menuRole.getMenuId()).collect(Collectors.toSet());
            List<MiddlegroundMenu> menuAll = middlegroundMenuRepository.findAllById(menuIds);
            List<MenuLoginResponse> menuLoginAll =new ArrayList<>();
            menuAll.forEach(menu->{
                MenuLoginResponse menuLoginResponse=new MenuLoginResponse();
                BeanUtils.copyProperties(menu,menuLoginResponse);
                menuLoginAll.add(menuLoginResponse);
            });
            RoleLoginResponse roleLoginResponse=new RoleLoginResponse();
            BeanUtils.copyProperties(role,roleLoginResponse);
            roleLoginResponse.setMenus(menuLoginAll);
            roleLoginResponses.add(roleLoginResponse);
        });
        middlegroundUserDetailsResponse.setRoles(roleLoginResponses);
        return Wrapper.success(middlegroundUserDetailsResponse);
    }

    /**
     * 删除用户信息
     *
     * @param request
     * @author wrc
     * @date 2020/7/23
     */
    @Transactional
    @Override
    public Wrapper middlegroundUserDeleteById(MiddlegroundUserDetailsRequest request, HttpServletRequest httpServletRequest) {
        if(request.getUserId().equals(1L)){
            return Wrapper.fail("不能删除超级管理员");
        }
        Optional<MiddlegroundUser> byId = middlegroundUserRepository.findById(request.getUserId());
        if(!byId.isPresent()){
            return Wrapper.fail("用户信息不存在");
        }
        MiddlegroundUser middlegroundUser = byId.get();
        if(CommonConstant.State.STATE_START==middlegroundUser.getState()){
            return Wrapper.fail("状态启用中无法删除");
        }
        MiddlegroundUserLoginResponse loginUserDetails = userDetailsUtil.getLoginUserDetails(httpServletRequest);
        if(loginUserDetails.getId().equals(request.getUserId())){
            return Wrapper.fail("不能删除当前登录账号");
        }
        middlegroundUserRepository.delete(middlegroundUser);
        return Wrapper.success();
    }

    /**
    * 根据账号获取用户信息
    * @author wrc
    * @date 2020/5/21
    */
    public MiddlegroundUserLoginResponse getLoginMiddlegroundUserLoginResponse(String account){
        MiddlegroundUserLoginResponse middlegroundUserLoginResponse=new MiddlegroundUserLoginResponse();
        MiddlegroundUser middlegroundUser = middlegroundUserRepository.findByAccountEqualsAndStateEquals(account,RoleConstant.RoleState.ROLE_STATE_START);
        if(null==middlegroundUser){
            return null;
        }
        BeanUtils.copyProperties(middlegroundUser,middlegroundUserLoginResponse);
        //查询用户的角色信息和权限信息
        MiddlegroundRoleUser  middlegroundRoleUser =new MiddlegroundRoleUser();
        middlegroundRoleUser.setUserId(middlegroundUser.getId());
        Example<MiddlegroundRoleUser> middlegroundRoleUserExample = Example.of(middlegroundRoleUser);
        List<MiddlegroundRoleUser> roleUseAll = middlegroundRoleUserRepository.findAll(middlegroundRoleUserExample);
        //获得角色列表
        Set<Long> collect = roleUseAll.stream().map(roleUser -> roleUser.getRoleId()).collect(Collectors.toSet());
        List<MiddlegroundRole> allById = middlegroundRoleRepository.findAllById(collect);
        List<RoleLoginResponse>  roleLoginResponses=new ArrayList<>();
        allById.forEach(role->{
            //获得角色的菜单集合
            MiddlegroundMenuRole  middlegroundMenuRole =new MiddlegroundMenuRole();
            middlegroundMenuRole.setRoleId(role.getId());
            Example<MiddlegroundMenuRole> middlegroundMenuRoleExample = Example.of(middlegroundMenuRole);
            List<MiddlegroundMenuRole> menuRoleAll = middlegroundMenuRoleRepository.findAll(middlegroundMenuRoleExample);
            Set<Long> menuIds = menuRoleAll.stream().map(menuRole -> menuRole.getMenuId()).collect(Collectors.toSet());
            List<MiddlegroundMenu> menuAll = middlegroundMenuRepository.findAllById(menuIds);
            List<MenuLoginResponse> menuLoginAll =new ArrayList<>();
            menuAll.forEach(menu->{
                MenuLoginResponse menuLoginResponse=new MenuLoginResponse();
                BeanUtils.copyProperties(menu,menuLoginResponse);
                menuLoginAll.add(menuLoginResponse);
            });
            RoleLoginResponse roleLoginResponse=new RoleLoginResponse();
            BeanUtils.copyProperties(role,roleLoginResponse);
            roleLoginResponse.setMenus(menuLoginAll);
            roleLoginResponses.add(roleLoginResponse);
        });
        middlegroundUserLoginResponse.setRoles(roleLoginResponses);
        return middlegroundUserLoginResponse;
    }

}
